package com.wyj.service.imp;

import com.wyj.event.EventProducer;
import com.wyj.mapper.LoginTicketMapper;
import com.wyj.mapper.UserMapper;
import com.wyj.pojo.LoginTicket;
import com.wyj.pojo.User;
import com.wyj.pojo.event;
import com.wyj.service.UserService;
import com.wyj.util.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;

@Service
public class UserServiceImp implements UserService, CommunityConstant {

    @Autowired
    UserMapper userMapper;

    @Value("${server.servlet.context-path}")
    String contextPath;

    @Value("${community.path.domain}")
    String domain;

    @Autowired
    TemplateEngine templateEngine;

    @Autowired
    MailClient mailClient;

    @Autowired
    LoginTicketMapper loginTicketMapper;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    EventProducer eventProducer;


    @Override
    public User getUserById(int userId) {

        User catchUser = getCatchUser(userId);

        //如果还未存缓存的话 先初始化
        if (catchUser == null) {
            catchUser = inintCatchUser(userId);
        }
        return catchUser;
    }

    @Override
    public User getUserByEmail(String email) {
        return userMapper.selectByEmail(email);
    }

    @Override
    public User getUserByUsername(String username) {
        return userMapper.selectByName(username);
    }

    @Override
    public int updateUserStatus(int id, int status) {
        int raws = userMapper.updateStatus(id, status);

        //当更改数据库当中的user值的话  我们就需要讲我们的缓存中的key值进行更改。
        delKey(id);

        return raws;
    }

    @Override
    public Map<String, Object> register(User user) {
        Map<String, Object> map = new HashMap<>();

        if (user == null) {
            throw new IllegalArgumentException("参数不能为空");
        }

        if (StringUtils.isBlank(user.getUsername())) {
            map.put("usernameMsg", "账号不能为空");
            return map;
        }

        if (StringUtils.isBlank(user.getPassword())) {
            map.put("passwordMsg", "密码不能为空");
            return map;
        }

        if (StringUtils.isBlank(user.getEmail())) {
            map.put("emailMsg", "邮箱不能为空");
            return map;
        }
        //username是账号  password是密码
        User user1 = userMapper.selectByName(user.getUsername());
        if (user1 != null) {
            map.put("usernameMsg", "该账号已经存在");
            return map;
        }

        User user2 = userMapper.selectByEmail(user.getEmail());
        if (user2 != null) {
            map.put("emailMsg", "改邮箱已被注册");
            return map;
        }

        //注册账户 每个用户还有还有其他信息
        /**
         *     private int id;//已经在配置文件中设置成自增了
         *     private String username;
         *     private String password;
         *     private String salt;
         *     private String email;
         *     private int type;
         *     private int status;
         *     private String activationCode;
         *     private String headerUrl;
         *     private Date createTime;
         */
        //设置盐
        user.setSalt(CommunityUtil.getUUID().substring(0, 5));
        //将用户的密码跟盐一块设置用MD5加密
        user.setPassword(CommunityUtil.md5(user.getPassword() + user.getSalt()));
        //设置普通用户
        user.setType(0);
        //设置是否激活
        user.setStatus(0);
        //
        user.setActivationCode(CommunityUtil.getUUID());
        //设置头像图片的连接
        user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png", new Random().nextInt(100)));
        //设置日期
        user.setCreateTime(new Date());

        //在这个user表中进行添加
        userMapper.insertUser(user);

        //发送验证邮件
        Context context = new Context();
        context.setVariable("mail", user.getEmail());

        String name = user.getUsername();
        User user3 = userMapper.selectByName(name);

        // http://localhost:8080/community/activation/101/code
        String url = domain + contextPath + "/activation/" + user3.getId() + "/" + user.getActivationCode();

        context.setVariable("url", url);


        //触发发送事件
        event event = new event();
        event.setTopic(TOPIC_MAIL);
        event.setData("context",context);
        event.setData("user",user);

        eventProducer.fireEvent(event);

    //        String content = templateEngine.process("/mail/activation", context);
    //        mailClient.sendMail(user.getEmail(), "激活账号", content);

        return map;
    }

    @Override
    public Map<String, Object> login(String username, String password, long expiredSeconds) {
        Map<String, Object> map = new HashMap();

        //空值处理
        if (StringUtils.isBlank(username)) {
            map.put("usernameMsg", "用户名不能为空");
            return map;
        }

        if (StringUtils.isBlank(password)) {
            map.put("passwordMsg", "密码不能为空");
            return map;
        }

        //验证账号 账号是否存在
        User user = userMapper.selectByName(username);
        if (user == null) {
            map.put("usernameMsg", "该用户不存在");
            return map;
        }

        //验证密码  密码是否正确
        password = CommunityUtil.md5(password + user.getSalt());
        System.out.println("数据库"+user.getPassword());
        System.out.println("输入的"+password);

        if (!user.getPassword().equals(password)) {
            map.put("passwordMsg","密码不正确");
            return map;
        }

        //验证状态 主要看该账号是否被激活
        if (user.getStatus() == 0) {
            map.put("usernameMsg","该账号未激活");
            return map;
        }

        //生成登录凭证
        LoginTicket loginTicket = new LoginTicket();
        loginTicket.setUserId(user.getId());
        loginTicket.setTicket(CommunityUtil.getUUID());
        loginTicket.setStatus(0);//设置登录状态 0 为登录状态
        //expiredSeconds是方法参数
        loginTicket.setExpired(new Date(System.currentTimeMillis()+expiredSeconds*1000));

        //这里是将凭证入库
//        loginTicketMapper.insertLoginTicket(loginTicket);
        //我们可以将凭证入Redis中,loginTicket.getTicket():表示的是一串凭证
        String redisKey = RedisKeyUtil.getLoginTicket(loginTicket.getTicket());
        redisUtil.set(redisKey,loginTicket);

        map.put("ticket",loginTicket.getTicket());

        return map;
    }
    /**
    * @Description 推出登录的时候要更改凭证
    * @param
    * @retuen int
    * @author wyj
    * @since  2022/7/30 11:39

    */
    @Override
    public void updateLoginTicket(String ticket) {
        //int updateLoginTicket = loginTicketMapper.updateLoginTicket(ticket, 1);

        String rediskey = RedisKeyUtil.getLoginTicket(ticket);
        LoginTicket loginTicket = (LoginTicket) redisUtil.get(rediskey);
        loginTicket.setStatus(1);

        //将新的凭证对象装进set容器当中
        redisUtil.set(rediskey,loginTicket);
//        revturn updateLoginTicket;
    }

    /**
    * @Description 每次走请求的时候都需要获取凭证
    * @param
    * @retuen com.wyj.pojo.LoginTicket
    * @author wyj
    * @since  2022/7/30 11:43

    */
    @Override
    public LoginTicket getLoginTicket(String ticket) {
//        LoginTicket loginTicket = loginTicketMapper.selectLoginTicketById(ticket);
        String redisKey = RedisKeyUtil.getLoginTicket(ticket);
        LoginTicket loginTicket = (LoginTicket) redisUtil.get(redisKey);

        return loginTicket;
    }

    @Override
    public int updateUserHeaderUrl(int id, String headerUrl) {
        int i = userMapper.updateHeaderUrl(id, headerUrl);
        return i;
    }

    //设置激活码的不同状态,因为当我们点开邮箱的时候只需要激活一次就行了
    //如果我们点击多次的话,那么就会有问题,所以的话 我们设置了
    //3个状态 1 表示已激活  0表示未激活  2表示激活失败
    public int activation(int userId, String code) {
        User user = userMapper.selectById(userId);
        if (user.getStatus() == 1) {
            return ACTIVATION_REPEAT;
        } else if (user.getActivationCode().equals(code)) {
            userMapper.updateStatus(userId, 1);
            return ACTIVATION_SUCCESS;
        } else {
            return ACTIVATION_FAILURE;
        }
    }


    /**
    * @Description 优先从缓存当中取值
    * @param
    * @retuen
    * @author wyj
    * @since  2022/7/30 12:29
    */
    public User getCatchUser(int userId) {
        String userKey = RedisKeyUtil.getUser(userId);
        User user = (User) redisUtil.get(userKey);
        return user;
    }

    /**
    * @Description 取不到的时候初始化数据
    * @param
    * @retuen
    * @author wyj
    * @since  2022/7/30 12:32

    */
    public User inintCatchUser(int userId) {
        User user = userMapper.selectById(userId);
        String userKey = RedisKeyUtil.getUser(userId);
        redisUtil.set(userKey,user,3600);

        return user;
    }

    /**
    * @Description 数据更改时候删除key
    * @param
    * @retuen
    * @author wyj
    * @since  2022/7/30 12:49

    */
    public void delKey(int userId) {
        String userKey = RedisKeyUtil.getUser(userId);
        redisUtil.del(userKey);
    }


    /**
    * @Description 获取用户的权限
    * @param
    * @retuen
    * @author wyj
    * @since  2022/8/9 23:06
    */

    public Collection<? extends GrantedAuthority> getAuthorities(int userId) {
        User user = userMapper.selectById(userId);

        List<GrantedAuthority> list = new ArrayList<>();

        list.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                switch (user.getType()) {
                    case 1:
                        return AUTHORITY_ADMIN;
                    case 2:
                        return AUTHORITY_MODERATOR;
                    default:
                        return AUTHORITY_USER;
                }
            }
        });


        return list;
    }



}
